import type { ReactNode } from 'react'
import type { PageHelperType } from '../../types.ts'
import React, { useEffect, useRef, useState } from 'react'
import './stream-list.scss'

interface StreamListProps {
  /**
   * 子组件内容
   */
  children: ReactNode
  /**
   * 请求下一页数据的函数
   * @param page
   * @param rows
   */
  onNextPage: (page: number, rows: number) => Promise<PageHelperType>
  /**
   * 请求刷新数据的函数
   */
  onRefreshPage: () => Promise<PageHelperType>
  /**
   * 刷新中的文字提示
   */
  refreshingText?: string
  /**
   * 加载中的文字提示
   */
  loadingText?: string
  /**
   * 加载更多的文字提示
   */
  loadMoreText?: string
}

/**
 * StreamList 组件
 */
const StreamList: React.FC<StreamListProps> = (
  {
    children,
    onNextPage,
    onRefreshPage,
    refreshingText = '正在刷新中...',
    loadingText = '加载中...',
    loadMoreText = '加载更多',

  }) => {
  const [page, setPage] = useState<number>(0)
  const [isLoading, setIsLoading] = useState<boolean>(false)
  const [isRefreshing, setIsRefreshing] = useState(false)
  const [isLastPage, setIsLastPage] = useState(false)
  // 下拉刷新的阈值
  const threshold = 50
  // 最大下拉距离
  const maxPullDistance = 100
  const [pullDistance, setPullDistance] = useState(0)
  const startYRef = useRef(0)
  const [isDragging, setIsDragging] = useState(false)
  const observerRef = useRef<IntersectionObserver | null>(null)
  // 防止初始加载直接请求下一页
  const hasInitialLoad = useRef(false)

  // 监听加载下一页数据
  useEffect(() => {
    if (isRefreshing || isLastPage || !hasInitialLoad.current)
      return
    const spinElement = document.querySelector('.spin')
    if (spinElement && !observerRef.current) {
      // 创建 IntersectionObserver 观察器
      observerRef.current = new IntersectionObserver((entries) => {
        const entry = entries[0]
        if (entry.isIntersecting && !isLoading) {
          setIsLoading(true)
          const nowPage = page + 1
          onNextPage(nowPage, 10)
            .then((res) => {
              setPage(nowPage)
              setIsLastPage(res.isLastPage)
            })
            .catch((err) => {
              console.error('加载下一页失败:', err)
            })
            .finally(() => setIsLoading(false))
        }
      }, { threshold: 1.0 })
      // 观察加载更多元素
      observerRef.current.observe(spinElement)
    }

    return () => {
      if (observerRef.current) {
        // 清除观察者
        observerRef.current.disconnect()
        observerRef.current = null
      }
    }
  }, [page, isLoading, isRefreshing, isLastPage])

  // 初始化加载标记
  useEffect(() => {
    hasInitialLoad.current = true
  }, [])

  // 处理触摸和鼠标事件
  const handleTouchStart = (e: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => {
    startYRef.current = 'touches' in e ? e.touches[0].clientY : e.clientY
    setIsDragging(true)
  }

  const handleTouchMove = (e: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => {
    if (isRefreshing || (!isDragging && !('touches' in e)))
      return

    const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY
    const distance = clientY - startYRef.current

    // 更新下拉距离
    if (distance > 0 && distance <= maxPullDistance) {
      setPullDistance(distance)
    }
    else if (distance > maxPullDistance) {
      setPullDistance(maxPullDistance)
    }
  }

  const handleTouchEnd = async () => {
    setIsDragging(false)
    if (pullDistance > threshold) {
      setIsRefreshing(true)
      setPullDistance(0)
      onRefreshPage()
        .then((res) => {
          setPage(res.page)
          setIsLastPage(res.isLastPage)
        })
        .catch((err) => {
          console.error('刷新失败:', err)
        })
        .finally(() => {
          setIsRefreshing(false)
        })
    }
    else {
      setPullDistance(0) // 重置下拉距离
    }
  }

  return (
    <div
      onTouchStart={handleTouchStart}
      onTouchMove={handleTouchMove}
      onTouchEnd={handleTouchEnd}
      onMouseDown={handleTouchStart}
      onMouseMove={handleTouchMove}
      onMouseUp={handleTouchEnd}
      className="stream-list-container"
    >
      <div
        className="refresh-indicator"
        style={{
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
          transform: `translateY(${isRefreshing ? threshold : pullDistance}px)`,
          transition: isRefreshing || pullDistance === 0 ? 'transform 0.3s ease' : 'none',
        }}
      >
        {isRefreshing && <span>{refreshingText}</span>}
      </div>
      <div style={{ transform: `translateY(${isRefreshing ? threshold : pullDistance}px)`, transition: 'transform 0.3s ease' }}>
        {children}
      </div>
      {!isRefreshing && !isLastPage && (
        isLoading
          ? <div className="loading-text">{loadingText}</div>
          : <div className="spin">{loadMoreText}</div>
      )}
    </div>
  )
}

StreamList.displayName = 'StreamList'
export default StreamList
